﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using AssetManagementSystem.Model;
using AssetManagementSystem.Presenter;
using AssetManagementSystem.Utils;
using AssetManagementSystem.Utils.Events;
using AssetManagementSystem.View.IView;

namespace AssetManagementSystem.View.Controls {
    public partial class ControlLoans : UserControl, ILoanView  {


        Dictionary<int, Loan> loanList;

        //==================================================
        // ILoanView Events
        //==================================================
        public event EventHandler Loans_LoadAll;
        public event EventHandler<SearchEventArgs> Loans_Find;
        public event EventHandler<LoanEventArgs> Loan_Create;
        public event EventHandler<LoanEventArgs> Loan_Return;
        public event EventHandler<LoanAssetEventArgs> LoanAsset_Return;
        public event EventHandler LoanAssets_LoadAvailable;
        public event EventHandler<LoanEventArgs> Loan_Notify;
        //==================================================

        //==================================================
        // View Constructor
        //==================================================
        public ControlLoans() {
            InitializeComponent();
            loanList = new Dictionary<int, Loan>();

            //Create loan presenter
            LoanPresenter loanPresenter = new LoanPresenter(this);
            //fire event to request a list of all loans
            this.Loans_LoadAll.Invoke(this, new EventArgs());
        }
        //==================================================

        public void RefreshAll() {
            this.Loans_LoadAll.Invoke(this, new EventArgs());
        }

        //==================================================
        // ILoanView Methods
        //==================================================
        public void SetLoanList(List<Loan> loans) {
            this.loanList.Clear();
            foreach (Loan loan in loans) {
                loanList.Add(loan.Id, loan);
            }
            RefreshLoansDisplay();
        }
        public void SetAvailableAssets(List<Asset> assets) { 
            //unused 
        }
        //==================================================

        //==================================================
        // Shared Interface Methods
        //==================================================
        public void ShowMessage(string message) {
            MessageBox.Show(message);
        }
        //==================================================


        public void RefreshLoansDisplay() {
            gridLoans.Rows.Clear();
            foreach (KeyValuePair<int, Loan> loan in loanList) {
                string loanDays = loan.Value.GetDaysLeft().ToString();
                if (loan.Value.IsOverdue()) {
                    loanDays = "Overdue";
                } else if (loan.Value.IsReturned()) {
                    loanDays = "Returned";
                }
                gridLoans.Rows.Add(loan.Value.StudentId, loan.Key.ToString(), loan.Value.StartDate.ToString("dd/MM/yyyy"), loan.Value.DueDate.ToString("dd/MM/yyyy"), loan.Value.Assets.Count, loanDays);
            }
        }

        public void RefreshLoanAssetsDisplay() {
            gridLoansAssets.Rows.Clear();
            if (gridLoans.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0) {
                foreach (KeyValuePair<string, DateTime> loanAsset in loanList[Convert.ToInt32(gridLoans.SelectedRows[0].Cells["LoanNo"].Value)].Assets) {
                    string status = "Returned: " + loanAsset.Value.ToString("dd/MM/yyyy");
                    if (loanAsset.Value == DateTime.MinValue) {
                        status = "On Loan";
                    }
                    gridLoansAssets.Rows.Add(loanAsset.Key.ToString(), status);
                }
            }
        }

        /// <summary>
        /// Fires the loan search event when the search button is clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSearch_Click(object sender, EventArgs e) {
            this.Loans_Find(this, new SearchEventArgs(txtSearch.Text, "Loan"));
        }

        /// <summary>
        /// Fires the search event when the 'Enter' key is clicked in the search textbox
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtSearch_KeyDown(object sender, KeyEventArgs e) {
            //perform search when enter key is pressed
            if (e.KeyCode == Keys.Enter) {
                this.btnSearch_Click(this, e);
            }
        }

        /// <summary>
        /// Displays the assets associated with the currently selected student loan.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridLoans_SelectionChanged(object sender, EventArgs e) {
            RefreshLoanAssetsDisplay();
        }

        private void btn_ReturnLoan_Click(object sender, EventArgs e) {
            if (gridLoans.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0) {
                    //Check if the user wants to return this loan
                    DialogResult dialogResult = MessageBox.Show("Are you sure you want to return this loan? The operation cannot be undone.",
                        "Return Loan", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (dialogResult == DialogResult.Yes) {
                        Loan retLoan = loanList[Convert.ToInt32(gridLoans.SelectedRows[0].Cells["LoanNo"].Value)];
                        LoanEventArgs args = new LoanEventArgs(retLoan);
                        this.Loan_Return.Invoke(this, args);
                        RefreshLoansDisplay();
                    }
            }
        }

        private void btn_ReturnItem_Click(object sender, EventArgs e) {
            if (gridLoans.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0 && gridLoansAssets.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0) {
                //Check if the user wants to return this loan
                    DialogResult dialogResult = MessageBox.Show("Are you sure you want to return this loan items? The operation cannot be undone.",
                        "Return Loan", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (dialogResult == DialogResult.Yes) {
                        Loan retLoan = loanList[Convert.ToInt32(gridLoans.SelectedRows[0].Cells["LoanNo"].Value)];
                        string assetId = (string)gridLoansAssets.SelectedRows[0].Cells["assetId"].Value;

                        LoanAssetEventArgs args = new LoanAssetEventArgs(retLoan, assetId);
                        this.LoanAsset_Return.Invoke(this, args);
                        RefreshLoansDisplay();
                    }
            }
        }

        private void btn_AddLoan_Click(object sender, EventArgs e) {
            UILoanEditor loanEdit = new UILoanEditor();
            loanEdit.Show();
            loanEdit.FormClosing += new FormClosingEventHandler(loanEditorClosed);
        }

        private void loanEditorClosed(object sender, EventArgs e) {
            RefreshAll();
        }

        private void btnNotify_Click(object sender, EventArgs e) {

            if (gridLoans.Rows.GetRowCount(DataGridViewElementStates.Selected) > 0) {
                Loan overdueLoan = loanList[Convert.ToInt32(gridLoans.SelectedRows[0].Cells["LoanNo"].Value)];
                if (overdueLoan.IsOverdue()) {
                    //Check if the user would like to generate a notification
                    DialogResult dialogResult = MessageBox.Show("Are you sure you want to send a notification to " + overdueLoan.StudentId + "?",
                        "Generate Notifications", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (dialogResult == DialogResult.Yes) {
                        LoanEventArgs args = new LoanEventArgs(overdueLoan);
                        this.Loan_Notify.Invoke(this, args);
                    }
                } else {
                    MessageBox.Show("The selected loan is not overdue.");
                }
            }


        }
    }
}
